'use strict';

/**
 * @ngdoc directive
 * @name jgappApp.directive:pullrefresh
 * @description
 * # pullrefresh
 */
angular.module('jgappApp')
    .directive('pullRefresh', function() {
        return {
            restrict: 'AE',
            scope: {
                loadingFunction: "="
            },

            link: function postLink(scope, element, attrs) {
                var $elem = $(element);
                var defaults = {
                    ptrEl: 'ptr',
                    offset: $elem.offset().top,
                    // Number of pixels of panning until refresh 
                    distanceToRefresh: 40,
                    // Dragging resistance level
                    resistance: 2.5
                };

                /**
                 * Hold all of the merged parameter and default module options
                 * @type {object}
                 */
                var options = {};

                /**
                 * Pan event parameters
                 * @type {object}
                 */
                var pan = {
                    enabled: false,
                    distance: 0,
                    startingPositionY: 0
                };

                /**
                 * Easy shortener for handling adding and removing body classes.
                 */
                var bodyClass = element[0].classList;

                /**
                 * Initialize pull to refresh, hammer, and bind pan events.
                 * 
                 * @param {object=} params - Setup parameters for pull to refresh
                 */
                var init = function(params) {
                    params = params || {};
                    options = {
                        contentEl: element[0],
                        ptrEl: params.ptrEl || document.getElementById(defaults.ptrEl),
                        distanceToRefresh: params.distanceToRefresh || defaults.distanceToRefresh,
                        loadingFunction: scope.loadingFunction,
                        resistance: params.resistance || defaults.resistance
                    };

                    if (!options.contentEl || !options.ptrEl) {
                        return false;
                    }

                    // var h = new Hammer(options.contentEl);
                    var h = new Hammer(options.contentEl, { "touchAction": "auto" });

                    h.get('pan').set({ direction: Hammer.DIRECTION_VERTICAL });

                    h.on('panstart', _panStart);
                    h.on('pandown', _panDown);
                    // h.on('panup', _panUp);
                    h.on('panend', _panEnd);
                };

                /**
                 * Determine whether pan events should apply based on scroll position on panstart
                 * 
                 * @param {object} e - Event object
                 */
                var _panStart = function(e) {
                    pan.startingPositionY = document.body.scrollTop;

                    if (pan.startingPositionY === 0) {
                        pan.enabled = true;
                    }
                };

                /**
                 * Handle element on screen movement when the pandown events is firing.
                 * 
                 * @param {object} e - Event object
                 */
                var _panDown = function(e) {
                    if (!pan.enabled) {
                        return;
                    }
                    e.preventDefault();
                    pan.distance = e.distance / options.resistance;

                    _setContentPan();
                    _setBodyClass();
                };

                /**
                 * Handle element on screen movement when the pandown events is firing.
                 * 
                 * @param {object} e - Event object
                 */
                var _panUp = function(e) {
                    console.log("up")
                    if (!pan.enabled || pan.distance === 0) {
                        return;
                    }

                    e.preventDefault();

                    if (pan.distance < e.distance / options.resistance) {
                        pan.distance = 0;
                    } else {
                        pan.distance = e.distance / options.resistance;
                    }

                    _setContentPan();
                    _setBodyClass();
                };

                /**
                 * Set the CSS transform on the content element to move it on the screen.
                 */
                var _setContentPan = function() {
                    // Use transforms to smoothly animate elements on desktop and mobile devices
                    options.contentEl.style.transform = options.contentEl.style.webkitTransform = 'translate3d( 0, ' + pan.distance + 'px, 0 )';
                    options.ptrEl.style.transform = options.ptrEl.style.webkitTransform = 'translate3d( 0, ' + (pan.distance - options.ptrEl.offsetHeight) + 'px, 0 )';
                };

                /**
                 * Set/remove the loading body class to show or hide the loading indicator after pull down.
                 */
                var _setBodyClass = function() {
                    if (pan.distance > options.distanceToRefresh) {
                        bodyClass.add('ptr-refresh');
                    } else {
                        bodyClass.remove('ptr-refresh');
                    }
                };

                /**
                 * Determine how to animate and position elements when the panend event fires.
                 * 
                 * @param {object} e - Event object
                 */
                var _panEnd = function(e) {
                    if (!pan.enabled) {
                        return;
                    }
                    // console.log($elem.position().top)
                    e.preventDefault();

                    options.contentEl.style.transform = options.contentEl.style.webkitTransform = '';
                    options.ptrEl.style.transform = options.ptrEl.style.webkitTransform = '';

                    if (element[0].classList.contains('ptr-refresh')) {
                        _doLoading();
                    }

                    pan.distance = 0;
                    pan.enabled = false;
                };

                /**
                 * Position content and refresh elements to show that loading is taking place.
                 */
                var _doLoading = function() {
                    if (defaults.offset != $elem.offset().top) {
                        return
                    }
                    bodyClass.add('ptr-loading');

                    // If no valid loading function exists, just reset elements
                    if (!options.loadingFunction) {
                        return _doReset();
                    }

                    // The loading function should return a promise
                    var loadingPromise = options.loadingFunction();

                    // For UX continuity, make sure we show loading for at least one second before resetting
                    setTimeout(function() {
                        // Once actual loading is complete, reset pull to refresh
                        loadingPromise.then(_doReset);
                    }, 1000);
                };

                /**
                 * Reset all elements to their starting positions before any paning took place.
                 */
                var _doReset = function() {
                    bodyClass.remove('ptr-loading');
                    bodyClass.remove('ptr-refresh');
                    bodyClass.add('ptr-reset');

                    var bodyClassRemove = function() {
                        bodyClass.remove('ptr-reset');
                        element[0].removeEventListener('transitionend', bodyClassRemove, false);
                    };

                    element[0].addEventListener('transitionend', bodyClassRemove, false);
                    // var vh = ($elem.parent().height() - $elem.height())+"px"
                    // $elem.css({ transform: "translate(0,"+vh+")" })
                };

                init()
            }
        };
    });
